home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fritz: All Fritz
/
All Fritz.zip
/
All Fritz
/
FILES
/
PROGSCAL
/
TBUTIL1.LZH
/
TERM.ASM
< prev
next >
Wrap
Assembly Source File
|
1984-02-22
|
34KB
|
1,052 lines
.xlist
;-----------------------------------------------------------------------------
; TELECOMM
; FAST TELECOMMUNICATION
;
; This program handles communication between two computers running the
; program. It allows you to either transmit or receive a file with
; error checking. An array is used as the buffer to transmit and receive
; to/from. The program will alert the calling program of any errors.
; Buffered communications are handled by a modified version of CJ Dunford's
; Dumterm program from PC Tech Journal, Jan '84, p144-186.
;-----------------------------------------------------------------------------
bufsize equ 512 ;1/2K Buffer
LF equ 0Ah
CR equ 0Dh
ESC equ 1Bh
RECEIVE EQU 1 ;Blocks are to be SENT
TRANSMIT EQU 2 ;Blocks are to be RECEIVED
CHK_SUM_ERR EQU 1 ;We have a CheckSum Error
TIME_OUT_ERR EQU 2 ;We have a TIMEOUT Error
PROTOCOL_ERR EQU 3 ;We have a PROTOCOL COMM Error
NUM_OF_UNITS EQU 0F000h ;Each unit is 0.00x seconds
;Codes sent by TRANSMIT:
TRANS_SIZE EQU 0F0h ;Send blk of NN size
DONE_TRANS EQU 0F1h ;Transmission is done
CHK_SUM_IS EQU 0F2h ;Checksum is NNNN
;Codes sent by RECEIVE:
OK_SEND EQU 0F3h ;Ok to send DATA
OK_DONE EQU 0F4h ;We're done too
CHK_SUM_OK EQU 0F5h ;Checksum is OK
ERR_RE_XMIT EQU 0F6h ;Comm. Error, send again
; ------- BIOS calls
RS232 equ 14h ;RS232 service
kbd_io equ 16h ;Keyboard service
; ------- INS8250 registers
THR equ 3F8h ;Trans holding register (write)
RBR equ 3F8h ;Recieve buffer register (read)
IER equ 3F9h ;Interrupt inable register
LCR equ 3FBh ;Line control register
; Bit 7 of LCR is "DLAB". DLAB must
; be zero to access THR, RBR, IER.
MCR equ 3FCh ;Modem control register
LSR equ 3FDh ;Line status register
MSR equ 3FEh ;Modem status register
; ------- Comm parameter definition
; Refer to IBM Tech Ref manual page A-20
; See PROC INIT for usage.
; ---------------------------------------
commparm record baud:3, parity:2, stopbits:1, wordbits:2
; Buad rates
B110 equ 000b
B150 equ 001b
B300 equ 010b
B600 equ 011b
B1200 equ 100b
B2400 equ 101b
B4800 equ 110b
B9600 equ 111b
; Parity
no_parity equ 00b
odd_parity equ 01b
even_parity equ 11b
; Stop bits
stop1 equ 0
stop2 equ 1
; Data bits
data7 equ 10b
data8 equ 11b
;*****************************
; MACROS
;*****************************
MWRITE MACRO string
local mstrng, mw10
jmp mw10
mstrng db string,lf,cr,'$'
mw10: push dx
lea dx, mstrng[bp]
call strdisp
pop dx
ENDM
MPOP MACRO DEST ;Move the stack addr. into DEST
POP AX
MOV DEST, AX
ENDM
MPUSH MACRO SOURCE ;Push the SOURCE onto the Stack
MOV AX, SOURCE
PUSH AX
ENDM
MVWRD MACRO DEST, SOURCE ;Move %1 <== %2
MOV si, SOURCE
MOV DEST, si
ENDM
MVWRDsi MACRO DEST, SOURCE ;Move %1 <== [%2] (source indirect)
MOV si, SOURCE
mov si, ds:[si]
MOV DEST, si
ENDM
MVWRDdi MACRO DEST, SOURCE ;Move [%1] <== %2 (dest indirect)
MOV di, DEST
mov si, SOURCE
MOV ds:[di], si
ENDM
@bioscall MACRO call_num, parm
;; Generates an 'INT call_num', with parm in AH
IFNB <parm>
mov ah,parm
ENDIF
int call_num
ENDM
@doscall MACRO function, parm
;; Generates a DOS function call with parm in AH
IFNB <parm>
mov al,parm
ENDIF
@bioscall 21h,function
ENDM
;******************************
; DATA & STACK STORAGE
;******************************
code segment para public 'code'
assume cs:code, ds:code, ss:code, es:code
public telecomm
telecomm proc near
CALL BEGIN
BasePage DW ? ;Storage for BP reg
DataSeg DW ? ;Storage for DS reg
ERROR DW ? ;Parameters passed by the stack
BLK_SIZE DW ?
BUF_SIZE DW ?
COMMAND DW ?
ARRAY DW ?
BUF_ARRAY DB 10000 DUP (?) ;4K Buffer
RETURN DW ? ;Temporary registers
BLK_SZ DW ?
BUF_SZ DW ?
ERR DW ?
CHK_SUM_1 DW ? ;Data checksum regs
CHK_SUM_2 DW ?
TIME_CNT DW ? ;Used to count time in inp loop
TIME_CNT1 DW ?
TEMP DW ?
ERR_COUNT DW ?
TMP_ARRAY DW ?
; ----- The string section
sgreeting db '--- ONLINE ---',cr,lf,'$'
sgoodbye db cr,lf,'--- OFFLINE ---',cr,lf,'$'
serr1 db '<R>$' ;RS232 receive error
serr2 db '<S>$' ;RS232 send error
serr3 db '<B>$' ;Receive buffer overflow error
; ----- Flags
brcv_err db 0 ;Nonzero on RS232 receive error
boverflow db 0 ;Nonzero on buffer overflow
bdoneflag db 0 ;Nonzero after ESC from kbd
; ----- Receive data buffer and associated pointers
; >> Buffer is empty if head point4er = tail pointer
wbufhead dw ? ;Pointer to head of buffer
wbuftail dw ? ;Pointer to tail of buffer
buffer db BUFSIZE dup (?)
bufend dw ?
;* * * * * * * * * * * * * * * * *
; PROGRAM BODY
;* * * * * * * * * * * * * * * * *
BEGIN PROC NEAR
pop ax ;Return the data seg
sub ax, 3 ;Adjust it
mov di, ax ;Ofset pointer to index reg
mov BasePage[di], bp ;Save old BP for exit
mov DataSeg[di], ds ;Save old DS for exit
mov bp, di ;Make BP the pointer
MPOP RETURN[bp] ;Save the RETURN Addr.
MPOP ERROR[bp] ;Error code on exit
pop ax
MPOP BLK_SIZE[bp] ;Length to send before chcksum
pop ax
MPOP BUF_SIZE[bp] ;Size of data in BLK units
pop ax
MPOP COMMAND[bp] ;What to do
pop ax
MPUSH RETURN[bp] ;Replace the Return Addr.
CALL OPEN_RS ;Set us up
CALL INITIALIZE ;Clear vars
CALL MAIN ;Do telecommunication
CALL CLOSE_RS
mov bp, BasePage[bp] ;Restore the BasePage
RET
BEGIN ENDP
;------WRITE_HEX------------------------------
; Displays 4 hexadecimal numbers contained in AX
; Entry:
; AX ==> 4 Hex numbers
; Exit:
; All regs but AX restored
;----------------------------------------------
Write_HEX PROC
push bx ;Save regs
push cx
push dx
mov bx, ax
mov cx, 12
shr ax, cl
call pr_one_hex
mov ax, bx
mov cx, 8
shr ax, cl
call pr_one_hex
mov ax, bx
mov cx, 4
shr ax, cl
call pr_one_hex
mov ax, bx
call pr_one_hex
pop dx
pop cx
pop bx
ret
pr_one_hex: and ax, 000Fh ;Mask LSD
cmp ax,9
ja wa20
add ax, '0'
jmp wa30
wa20: add ax, 'A'-10
wa30: mov dx, ax
@doscall 2 ;Print the char
ret
Write_HEX ENDP
;START OF PROGRAM:
INITIALIZE PROC NEAR ;Zero out variables
MOV ERR[bp], 0000
MOV TIME_CNT[bp], 0000
MOV CHK_SUM_1[bp], 0000
MOV CHK_SUM_2[bp], 0000
MVWRDsi BUF_SZ[bp], BUF_SIZE[bp] ;Move params to vars
MVWRDsi BLK_SZ[bp], BLK_SIZE[bp]
lea ax, buf_array[bp]
mov array[bp], ax
ret
INITIALIZE ENDP
MAIN PROC NEAR
mov si, command[bp]
cmp byte ptr ds:[si], transmit ;Shall we Transmit
JE SHORT M010 ;Go on to TRANSMT
CALL RECV_IT ;Read in the data
JMP SHORT M090
M010: CALL TRANS_IT ;Transmit the data
M090: MOV AX, ERR[bp]
MOV AH, 00 ;Zero MSD
mov bx, error[bp]
MOV ds:[bx], AX
RET
MAIN ENDP
RECV_IT PROC NEAR
; ---- Receive the data
MOV ERR_COUNT[bp], 00 ;Zero Error Count
R010: CALL READ_RS ;Get the trans code
MOV byte ptr TEMP[bp], al ;Save for later
cmp err[bp], 0
je R015
JMP R999 ;Error, Now exit
R015: MOV al, byte ptr TEMP[bp] ;Get back INP
CMP AL, TRANS_SIZE ;Code for blk_size
JE SHORT R030
CMP AL, DONE_TRANS ;Code for EOT
JNE SHORT R020
MOV AL, OK_DONE ;Tell them we're done
CALL WRITE_RS
MVWRDdi BUF_SIZE[bp], BUF_SZ[bp] ;Make BUF_SZ avail to caller
JMP R999
R020: CALL PRTCL_ERR_RPT ;Report Protocol error
JMP R999
R030: CALL READ_RS ;Read in BLK_SIZE
MOV byte ptr BLK_SZ[bp], AL
cmp ERR[bp], 00 ;If there was an err, exit
JNZ R999 ;Error, Now exit
R040: MOV AL, OK_SEND ;Tell them its OK to trans
CALL WRITE_RS
MVWRD TMP_ARRAY[bp], ARRAY[bp] ;Save for later
CALL ACPT_INFO ;Receive the DATA block
JNE SHORT R080 ;Note error, try again
CALL VRIFY_CHECKSUM ;Check if OK
JNE SHORT R080 ;Go report error
INC BUF_SZ[bp] ;Keep count of BLKs
MOV AL, CHK_SUM_OK ;Tell them CHK_SUM Ok
CALL WRITE_RS
JMP R010 ;Loop for next BLK
R080: MVWRD ARRAY[bp], TMP_ARRAY[bp] ;Restore ARRAY pointer
INC BYTE ptr ERR_COUNT[bp]
CMP ERR_COUNT[bp], 3 ;Can't be more than 3 Errors
JA R090 ;Report Error
MOV AL, ERR_RE_XMIT ;Tell them to send it again
CALL WRITE_RS
JMP R010
R090: cmp ERR[bp], 00 ;Report checksum error
JNZ R999 ;Dont alter a set error flag
MOV ERR[bp], CHK_SUM_ERR ;Set checksum error
R999: RET
RECV_IT ENDP
ACPT_INFO PROC NEAR
; ---- Read in the DATA blk
MOV AX, BLK_SZ[bp] ;Init BLK_SIZE
MOV AH, 00 ;Zero MSD
mov bx, blk_size[bp]
MOV ds:[bx], AX
MOV CHK_SUM_1[bp], 00 ;Zero out Checksum_1
A010: CALL READ_RS ;Read in first char
MOV byte ptr TEMP[bp], AL ;Save for later
cmp ERR[bp], 00
JNZ SHORT A999 ;Exit if Err
mov si, array[bp] ;Point to array addr.
mov al, byte ptr temp[bp] ;Move Input to BLK
mov byte ptr cs:[si], al
CALL CHK_SM_ADD ;Add to check sum figure
INC ARRAY[bp]
DEC BLK_SZ[bp]
JNZ SHORT A010 ;Loop till done
A999: RET ;NE means ERROR
ACPT_INFO ENDP
TRANS_IT PROC NEAR
; ---- Transmit the data
cmp BLK_SZ[bp], 00 ;First check Params
JNZ SHORT T001
JMP T999 ;Exit if 0 BLK_SIZE
T001: cmp BUF_SZ[bp], 00
JNZ SHORT T005
JMP T999 ;Exit if 0 BUF_SIZE
T005: MOV ERR_COUNT[bp], 00 ;Zero ERR_COUNT
T010: MOV AL, TRANS_SIZE ;Tell them the BLK_SIZE
CALL WRITE_RS
MOV ax, BLK_SZ[bp] ;LSD only
CALL WRITE_RS
CALL READ_RS ;Wait for OK_SEND
cmp err[bp], 00 ;If error, then protocol err
je T020 ;Skip if no error
jmp T999 ;Exit, if error
T020: CMP al, OK_SEND ;Check if INP is OK_SEND
JE SHORT T030 ;No Error, go on
MOV ERR[bp], PROTOCOL_ERR ;Report Protocol Err
JMP SHORT T999 ;Exit
T030: MVWRD TMP_ARRAY[bp], ARRAY[bp] ;Save if needed later
CALL SEND_INFO ;Transmit the DATA
CALL SEND_CHK_SUM ;Check if OK
JNE SHORT T080 ;Note Error, Try again
DEC BUF_SZ[bp]
JNZ SHORT T005 ;Loop up & reset ERR_COUNT
MOV AL, DONE_TRANS ;Tell them we're DONE
CALL WRITE_RS
CALL READ_RS ;Wait for OK_DONE
cmp err[bp], 00 ;If Err, set protocol Err
JNE SHORT T999
CMP al, OK_DONE ;Check INP vs OK_DONE
JE SHORT T999
MOV ERR[bp], PROTOCOL_ERR ;Tell them Protocol Error
JMP SHORT T999
T080: cmp ERR[bp], 00 ;Repeat if not fatal Error
JNZ SHORT T090 ;Mark CHK_SUM_ERR if so
MVWRD ARRAY[bp], TMP_ARRAY[bp] ;Restore ARRAY pointer
INC BYTE ptr ERR_COUNT[bp]
CMP ERR_COUNT[bp], 3 ;ERR_COUNT can't be > 3
JA short T090 ;Report Error
JMP T010 ;Try again
T090: cmp ERR[bp], 00 ;Report checksum error
JNZ short T999 ;Dont alter a set error flag
MOV ERR[bp], CHK_SUM_ERR ;Set checksum error
T999: RET
TRANS_IT ENDP
SEND_INFO PROC NEAR
; ---- Transmit the DATA
MOV CHK_SUM_1[bp], 00 ;Zero CHK_SUM_1
MVWRDsi BLK_SZ[bp], BLK_SIZE[bp] ;Reset the Block size var.
Si010: MOV si, ARRAY[bp] ;Send the Block
mov al, cs:[si]
CALL CHK_SM_ADD ;Add to check sum figure
CALL WRITE_RS
INC WORD ptr ARRAY[bp]
DEC WORD ptr BLK_SZ[bp]
JNZ SHORT Si010
MVWRDsi BLK_SZ[bp], BLK_SIZE[bp] ;Reset the Block size var.
RET
SEND_INFO ENDP
CHK_SM_ADD PROC NEAR
; ---- Add Char to check sum figure
PUSH AX
xor ah, ah ;Clear MSD
ADD CHK_SUM_1[bp], AX
POP AX
RET
CHK_SM_ADD ENDP
VRIFY_CHECKSUM PROC NEAR
; ---- Verify the equality of the chksums
CALL READ_RS ;Wait for CHK_SUM code
CMP al, CHK_SUM_IS
JE SHORT V010 ;Go on for chk_sum
CALL PRTCL_ERR_RPT ;Report Protocol error
JMP SHORT V999
V010: CALL READ_RS ;Get checksum
MOV byte ptr CHK_SUM_2[bp], AL
cmp err[bp], 00 ;Set protocol error if error
JNE SHORT V999 ;Exit on error
CALL READ_RS
MOV byte ptr CHK_SUM_2+1[bp], AL
cmp err[bp], 00 ;Set protocol error if error
JNE SHORT V999 ;Exit on error
MOV AX, CHK_SUM_2[bp] ;Now check equality of chk_sums
CMP AX, CHK_SUM_1[bp]
V999: RET ;NE if error
VRIFY_CHECKSUM ENDP
SEND_CHK_SUM PROC NEAR
MOV AL, CHK_SUM_IS ;Tell them CHK_SUM coming
CALL WRITE_RS
MOV al, byte ptr CHK_SUM_1[bp] ;LSD
CALL WRITE_RS
MOV al, byte ptr CHK_SUM_1+1[bp] ;MSD
CALL WRITE_RS
CALL READ_RS ;Wait for CHK_SUM_OK
cmp err[bp], 00 ;If Err then Protocol Err
JNE SHORT S999 ;Exit if Err
CMP al, CHK_SUM_OK ;Is it CHK_SUM_OK
JE SHORT S999 ;OK, Return
CMP al, ERR_RE_XMIT ;Is it ERR_RE_XMIT
JNE SHORT S010
MOV AL, ERR_RE_XMIT ;Set to NE to flag chksum error
cmp al, 00 ;Force setting of NE flag
JMP SHORT S999 ;Exit to do again
S010: MOV ERR[bp], PROTOCOL_ERR ;Tell them Protocol Error
cmp ERR[bp], 00 ;Force setting of NE flag
S999: RET
SEND_CHK_SUM ENDP
PRTCL_ERR_RPT PROC NEAR
; ---- Report protocol error
MOV ERR[bp], PROTOCOL_ERR ;Flag the comm error
cmp ERR[bp], 00 ;Set NE flag
RET
PRTCL_ERR_RPT ENDP
WRITE_RS PROC NEAR
call RS232_out
RET
WRITE_RS ENDP
READ_RS PROC NEAR
mov word ptr time_cnt1[bp], 3
Rd001: mov word ptr time_cnt[bp], num_of_units
Rd010: dec TIME_CNT[bp]
JNZ SHORT Rd020
dec time_cnt1[bp]
jnz Rd001
mov err[bp], TIME_OUT_ERR ;Signal Timeout
JMP SHORT Rd999
Rd020: mov bx, wbufhead[bp] ;Have char if not equal
cmp bx, wbuftail[bp]
JE SHORT Rd010 ;Loop if empty
call buffer_check ;Read from .RS232
Rd999: RET
READ_RS ENDP
OPEN_RS PROC NEAR
call init_rs232
RET
OPEN_RS ENDP
CLOSE_RS PROC NEAR
call cleanup_RS232
RET
CLOSE_RS ENDP
;* * * * * * * * * * * * * * * * * * * *
; PRIMARY RS232 BLOCKS
;* * * * * * * * * * * * * * * * * * * *
; ------ Init_rs232 --------------------------
;Program initialization
; set up RS232
; set up vector for RS232 interrupt (INT 0Ch)
; Enable IRQ4
; Enable RS232 interrupt on data ready
; --------------------------------------------
init_rs232 proc near
lea ax, buffer[bp]
mov wbufhead[bp], ax
mov wbuftail[bp], ax
; ----- Initialize RS232 9600,8,N,1
mov dx,0
mov al,commparm <B1200,no_Parity,stop1,data8>
@bioscall RS232,0
; ----- Set up INT '0C' for IRQ4
cli ;Interrupts off during setup
push ds ;Save DS
lea dx, ISR[bp] ;Point to RS232 ISR in DS:DX
push cs
pop ds
@doscall 25h,0Ch ;Set vector intr for IRQ4
pop ds ;Restore DS
; ------ Enable IRQ4 on 8259 interrupt controller
in al,21h ;Get current mask
and al,11101111b ;Reset IRQ4 mask
out 21h,al ;restore to IMR
; ------ Enable 8250 data ready interrupt
mov dx,LCR ;DX <== LCR
in al,dx ;reset DLAB for IER access
and al,01111111b
out dx,al
mov dx,IER ;address IER
mov al,00000001b ;Enable data-ready interrupt
out dx,al
; ------ Enable OUT2 on 8250
mov dx,MCR ;Address MCR
mov al,00001000b ;Enable OUT2
out dx,al
sti
; ------ Display greeting & return
lea dx, sgreeting[bp] ;Point to greeting
call strdisp ;Display it
ret
init_rs232 endp
; ------ Buffer Check ------------------
; RS232 buffer check
;
; This block checks the received data buffer.
; It functions as follows:
;
; If the RS232 input buffer is not empty
; Get the first character
; Display the character
; Update buffer pointer
; If the RS232 receive error flag is nonzero
; Display an error indicator
;
; Entry:
; No requirement
; Exit
; AX, BX, CX, DX destroyed
; --------------------------------------
buffer_check proc near
; ------ Check buffer status
mov bx,wbufhead[bp] ;buffer head pointer
cmp bx,wbuftail[bp] ;buffer empty if head = tail
je BC100
; ------ Something in buffer--get 1st char, fix pointers
mov al, cs:[bx] ;get the char
mov cl, al ;Save for later
call incptr ;Bump buffer head pointer
mov wbufhead[bp],bx
xor ah, ah
;call chdisp
; ------ Test RS232 receive status; display errors
BC100: Test brcv_err[bp],0FFh ;Flag nonzero if errors
jz BC200 ;Jump if no errors
lea dx, serr1[bp] ;Point to error msg
call strdisp
mov brcv_err[bp],0 ;Clear error flag
; ----- Test for buffer overflow; display errors
BC200:
test boverflow[bp], 0FFh
jz BC300
mov boverflow[bp],0 ;Clear the flag
lea dx, serr3[bp] ;Point to error msg
call strdisp
BC300: mov al, cl ;Replace input char
xor ah, ah ;Clear MSD
ret
buffer_check endp
; ----- KB_CHECK -----------------------------------
; Check the keyboard. Functions as follows
;
; Check the keyboard status
; If a characteris available
; If the character is ESC
; set the done flag
; ELSE
; send it to RS232 and watch for errors
;
; This routine does not echo the characters to the display.
;
; Entry:
; No requirement
; Exit
; AX, DX destroyed
; --------------------------------------
kb_check proc near
; ----- Poll keyboard, check chars received
call kb_poll ;Poll the keyboard
jz KBC900 ;Kbd clear, exit
cmp al,ESC ;Escape?
jne KBC100
mov bdoneflag[bp],0FFh ;Yes, set terminate flag
jmp short KBC900
; ----- Send the received char, watch for errors
KBC100: Call RS232_out ;Send it
test ah,80h ;Time out?
jz KBC900
lea dx, serr2[bp] ;Point to error msg
call strdisp ; and display
KBC900: ret
kb_check endp
; ----- ISR ------------------------------------------------------
; This is the RS232 interrupt service routine. It is entered
; whenever the RS232 port interrupts on a 'data ready'
; condition. The routine simply reads the data from the asynch
; chip and stuffs it in the buffer. Note that the process of reading
; the received data register in the 8250 clears IRQ4. However, the
; 8259 must be told specifically that the interrupt service is complete.
;
; This replaces the function 2 of BIOS interrupt 14h (receive a character
; over the comm line). Since it cannot return errors in a register, it
; puts the error marker in memory at 'brcv_err'. The error flag is
; sticky -- a successful read will not clear a prior error indication.
; This allows the program mainline to examine the error status at its
; leisure. Error bits are the same as in RS232OUT, above, except that
; ONLY the error bits are set, and bit 7 is not used (always 0). In
; other words, brcv_err is nonzero only on an error. Timeout errors
; are not possible here.
;
; The ISR will set the overflow flag if the buffer should overflow.
; This shouldn't happen.
; --------------------------------------------------------------------
ISR proc near
sti ;Allow other interrupts
push ax ;Save all regs used
push bx
push dx
push si
push ds
push cs
pop ds
; ---- Get error bits
mov dx,LSR ;Save address of RS232
in al,dx ;Get status
and al,00011110b ;Mask non-error bits
jz ISR010 ;Skip error set if OK
mov brcv_err[bp],al ;Set error indicator
; ---- Get incoming character and buffer it
ISR010: mov dx,RBR ;Receive buffer
in al,dx ;Get input buffer
mov bx,wbuftail[bp] ;Buffer input pointer
mov si,bx ;Set pointer before increment
call incptr ;Bump input pointer
cmp bx,wbufhead[bp] ;Overflow if head = tail
je ISR020 ;Overflow
mov cs:[si],al ;No overflow, save char in buf
mov wbuftail[bp],bx ;And new input pointer
jmp short ISR999
ISR020: mov boverflow[bp], 0FFh ;Set overflow flag
; ---- Signal end of interrupt to 8259
ISR999: cli
mov al,20h ;Non-specific EOI
out 20h,al ;Send it
; ---- Restore regs & return. IRET reenables interrupts
pop ds
pop si
pop dx
pop bx
pop ax
iret
ISR endp
; ---- CLEANUP_RS232 --------------
; End of program housekeeping
; -- Disable IRQ4
; -- Disable 8250 interrupts
; -- Disable OUT2
; -- Display offline message
; ---------------------------------
cleanup_rs232 proc near
mov ax, 0ffffh
cl01: dec ax
jne cl01
; ---- Disable IRQ4 on 8259
cli
in al,21h ;IMR
or al,00010000b ;Mask bit 4 -- IRQ4
out 21h,al
; ---- Disable 8250 data ready interrupt
mov dx, LCR ;DX <=== LCR
in al,dx ;Reset DLAB for IER access
and al,01111111b
out dx,al
mov dx,IER ;Address IER
mov al,0 ;Disable all 8250 interrupts
out dx,al
; ---- Disable OUT2 on 8250
mov dx,MCR ;Address MCR
mov al,0 ;Disable OUT2
out dx,al
sti
; ---- Display bye-bye
lea dx, sgoodbye[bp]
call strdisp
cleanup_rs232 endp
; * * * * * * * * * * * * * *
; I/O & General Subroutines
; * * * * * * * * * * * * * *
; ---- KB_POLL ------------------------------
; Set/reset Z flag on keyboard buffer status.
;
; Entry:
; No requirements
; Exit:
; Z = 1 if nothing available
; Z = 0 if char available from kbd
; IF Z = 0
; AL = char
; AH = scan code
; Other regs preserved
; ---------------------------------------------
kb_poll proc near
@bioscall kbd_io,1 ;Poll KB. Sets Z flag if KB bfr empty
jz KB999 ;Nothing there
pushf ;Save flag status
@bioscall kbd_io,0 ;Something there; get it
popf
KB999:
ret
kb_poll endp
; -- RS232_OUT ----------------------------------------
; RS232 output routine
;
; This routine sends one character to the RS232 port.
; It replaces function 1 of BIOS int 14K. This is
; necessary because BIOS will disable the RS232
; interrupt (by disabling OUT2) every time it is
; called.
;
; Entry:
; AL = character to be transmitted
; Exit:
; AH = send status
; Bit 7 = 1 if RS232 timeout occurred
; If bit 7 = 0
; bit 6: trans shift register empty
; bit 5: trans holding register empty
; bit 4: break detect
; bit 3: framing error
; bit 2: parity error
; bit 1: overrun error
; bit 0: data ready
; Other regs preserved.
; -------------------------------------------------------
RS232_out proc near
push bx ;Save regs used
push cs
push dx
mov ah, 1
call chdisp
; ----- Set up RS232
mov bl,al ;Save char to bl temporarily
mov dx,MCR ;Modem Control Register
mov al,00001011b ; OUT2, DTR, RTS
out dx,al
sub cx,cx ;Initialize timeout count
mov dx,MSR ;Modem Status Register
; ----- Wait for DSR
RS100:
in al,dx
test al,20h ;Data set ready?
jnz RS150 ;Yes
loop RS100 ;No, retry till timeout
mov ah,80h ;Set timeout
jmp short RSXIT ;and quit
; ----- Wait for CTS
RS150:
sub cx,cx ;Another timeout count
RS200:
in al,dx
test al,10h ;Clear to send?
jnz RS250 ;Yes
loop RS200 ;No, loop till timeout
mov ah,80h ;TImeout,set flag
jmp short RSXIT ;And quit
; ----- Wait for THRE
RS250:
mov dx,LSR ;Line Status Register
sub cx,cx ;Yes another timeout count
RS300:
in al,dx ;LSR status
test al,20h ;Transmit holding reg empty?
jnz RS350 ;Yes
loop RS300 ;No, loop till timeout
mov ah,80h ;Timeout, set flag
jmp short RSXIT
; ------ Get line status, send char
RS350:
mov ah,al ;Get line status for return
and ah,01111111b ;Mask out bit 7
mov al,bl ;Restore char to AL
mov dx,THR ;Transmit holding register
out dx,al ;Output it to RS232
RSXIT:
pop dx
pop cx
pop bx
ret
RS232_out endp
; ---- CHDISP ----------------------------------
; Display the character in AL on the CRT
; Entry:
; AL = char
; Exit:
; All regs restored
; ----------------------------------------------
chdisp proc near
push ax
push dx
mov dl, al
@doscall 2
pop dx
pop ax
ret
chdisp endp
; ---- STRDISP ----------------------------
; Display the string at DS:DX on the CRT
; Entry:
; DS:DX ==> string
; Exit:
; All regs restored
; -----------------------------------------
strdisp proc near
push ds
push cs
pop ds
push ax
@doscall 9
pop ax
pop ds
ret
strdisp endp
; ----- INCPTR ------------------------------
; Increments the buffer pointer in reg BX.
; If the pointer goes beyond the end of the
; buffer, wrap around to start.
;
; Entry:
; BX = buffer pointer
; Exit
; BX = advanced buffer pointer
; Other regs restored
; --------------------------------------------
incptr proc near
push ax
inc bx ; Bump pointer
lea ax, bufend[bp]
cmp bx, ax ; Past end?
jne IP100 ; Jump if not
lea bx, buffer[bp] ; Else point to start
IP100: pop ax
ret
incptr endp
telecomm endp
code ends
end telecomm